// Copyright (c) 2010 SuccessFactors, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//     * Redistributions of source code must retain the above
//       copyright notice, this list of conditions and the following
//       disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials
//       provided with the distribution.
//
//     * Neither the name of the SuccessFactors, Inc. nor the names of
//       its contributors may be used to endorse or promote products
//       derived from this software without specific prior written
//       permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

package org.owasp.jxt.tag.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.owasp.jxt.Attribute;
import org.owasp.jxt.JxtEngine;
import org.owasp.jxt.JxtRoot;
import org.owasp.jxt.JxtUtils;
import org.owasp.jxt.TranslateContext;

/**
 * AbstractRootNode
 *
 * @author Jeffrey Ichnowski
 * @version $Revision: 8 $
 */
public abstract class AbstractRootNode extends AbstractCoreNode implements JxtRoot {
    private String _import;

    private String _encoding;
    private String _omitXmlDeclaration;
    private String _doctypePublic;
    private String _doctypeSystem;

    // Other attributes from XSLT, not included here.
//     private String _method;
//     private String _version;
//     private String _standalone;
//     private String _cdataSectionElements;
//     private String _indent;
//     private String _mediaType;

    protected AbstractRootNode(String tagName) {
        super(tagName);
    }

    @Attribute
    public final void setImport(String imports) {
        _import = imports;
    }

    @Attribute
    public final void setEncoding(String encoding) {
        _encoding = encoding;
    }

    @Attribute(pattern="yes|no")
    public final void setOmitXmlDeclaration(String oxd) {
        _omitXmlDeclaration = oxd;
    }

    @Attribute
    public final void setDoctypePublic(String dt) {
        _doctypePublic = dt;
    }

    @Attribute
    public final void setDoctypeSystem(String dt) {
        _doctypeSystem = dt;
    }

    protected final void translateHeader(TranslateContext ctx) {
        // TODO: this needs to be conditionally translateed.  The
        // <jxt:page> node cannot be included as a child if these
        // headers are embedded (it may not be known at translation
        // time if this page will be included dynamically as a child
        // of another, therefore it pretty much has to be a runtime
        // thing)

        // TODO: get encoding from somewhere
        // TODO: line endings

        if ("no".equals(_omitXmlDeclaration)) {
            ctx.data("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        }

        // TODO: get root element from somewhere
        String rootElement = "html";

        if (_doctypePublic != null) {
            ctx.data("<!DOCTYPE "+rootElement+" PUBLIC "+
                     JxtUtils.quoteAttribute(_doctypePublic)+" "+
                     JxtUtils.quoteAttribute(_doctypeSystem)+">\n");
        } else if (_doctypeSystem != null) {
            ctx.data("<!DOCTYPE "+rootElement+" SYSTEM "+
                     JxtUtils.quoteAttribute(_doctypeSystem)+">\n");
        }
    }

    protected void addStandardImports(List<String> imports) {
    }

    // TODO: roll up contained templates (imports, dependency
    // information, etc...)

    @Override
    public final void translate(TranslateContext ctx) {
        if (getParent() != null) {
            // included page fragment
            translateChildren(ctx);
        } else {
            ctx.codeln("// Automatically generated code.  Do not edit.");
            ctx.codeln("// Generated from "+ctx.getRootSourceFile()+" "+new java.util.Date());
            ctx.codeln("package "+JxtEngine.JXT_PACKAGE+";");
            ctx.codeln();

            List<String> imports = new ArrayList<String>();

            imports.add("org.owasp.jxt.JxtUtils");
            imports.add("org.owasp.jxt.Encoder");

            addStandardImports(imports);

            if (_import != null) {
                imports.addAll(Arrays.asList(_import.split(",")));
            }

            for (String imp : imports) {
                ctx.codeln("import "+(imp.trim())+";");
            }
            ctx.codeln();
            translateClass(ctx);
        }
    }

    protected abstract void translateClass(TranslateContext ctx);

} // AbstractRootNode
